package com.zju.cst.cloudApp.server;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.channel.group.ChannelGroup;
import org.jboss.netty.channel.group.ChannelGroupFuture;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.frame.FrameDecoder;

public class AppServer {

	public static final ChannelGroup allChannels = new DefaultChannelGroup(
			"time-server");

	// Default key
	private static String CHILD_TCPNODELAY = "child.tcpNoDelay";
	private static String CHILD_KEEPALIVE = "child.keepAlive";

	// properties
	private FrameDecoder decoder;
	private SimpleChannelHandler channelHandler;
	private int port;
	private ChannelFactory factory;

	public AppServer() {
		Runtime.getRuntime().addShutdownHook(new Thread() {
			public void run() {
				waitForShutdownCommand();
			}
		});
	}
	
	public void startListen() {
		factory = new NioServerSocketChannelFactory(
				Executors.newCachedThreadPool(),
				Executors.newCachedThreadPool());
		ServerBootstrap bootstrap = new ServerBootstrap(factory);
		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(decoder, channelHandler);
			}
		});

		bootstrap.setOption(CHILD_TCPNODELAY, true);
		bootstrap.setOption(CHILD_KEEPALIVE, true);

		Channel channel = bootstrap.bind(new InetSocketAddress(port));
		allChannels.add(channel);
	}

	public void waitForShutdownCommand() {
		System.out.println("===========do shutdown==============");
		ChannelGroupFuture future = allChannels.close();
		future.awaitUninterruptibly();
		factory.releaseExternalResources();
	}

	public FrameDecoder getDecoder() {
		return decoder;
	}

	public void setDecoder(FrameDecoder decoder) {
		this.decoder = decoder;
	}

	public SimpleChannelHandler getChannelHandler() {
		return channelHandler;
	}

	public void setChannelHandler(SimpleChannelHandler channelHandler) {
		this.channelHandler = channelHandler;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}
}
